/**
 * Baijiahulian.com Inc. Copyright (c) 2014-2016 All Rights Reserved.
 */
package com.baijia.web.controller;

import com.baijia.CentralAuthenticationService;
import com.baijia.authentication.AccountType;
import com.baijia.authentication.Authentication;
import com.baijia.authentication.AuthenticationMetaDataPopulator;
import com.baijia.authentication.principal.Credentials;
import com.baijia.authentication.principal.credentials.JigouCascadeAccountCredentials;
import com.baijia.authentication.principal.credentials.JigouCredentials;
import com.baijia.authentication.principal.credentials.MobileCredentials;
import com.baijia.authentication.principal.credentials.OrgTeacherCredentials;
import com.baijia.authentication.principal.credentials.PassportCredentials;
import com.baijia.authentication.principal.credentials.UserCredentials;
import com.baijia.common.enums.UserRoleType;
import com.baijia.services.PassportService;
import com.baijia.services.ServicesManager;
import com.baijia.ticket.Ticket;
import com.baijia.ticket.TicketGrantingTicket;
import com.baijia.ticket.registry.TicketRegistry;
import com.baijia.util.HttpClient;
import com.baijia.web.config.PassportConfig;
import com.baijia.web.dto.LoginInfoDto;
import com.baijia.web.extractor.CookieRetrievingCookieGenerator;
import com.baijia.web.extractor.DessionCookieCleaner;
import com.baijia.web.util.LoginAndLogoutUtil;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @title AbstractAuthorizeController
 * @desc TODO
 * @author macrohuang
 * @date Apr 12, 2016
 * @version 1.0
 */
public abstract class AbstractAuthorizeController {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    protected static final String APPID = "appId";

    @Resource
    protected TicketRegistry ticketRegistry;
    @Autowired
    protected CentralAuthenticationService centralAuthenticationService;
    @Autowired
    protected ServicesManager servicesManager;
    @Autowired
    protected CookieRetrievingCookieGenerator cookieRetrievingCookieGenerator;
    @Autowired
    protected DessionCookieCleaner dessionCookieCleaner;
    @Autowired
    protected HttpClient httpClient;

    @Resource
    protected PassportService passportService;

    @Resource
    protected PassportConfig passportConfig;

    private PassportCredentials generatePassportCredentials(HttpServletRequest request, boolean isSms) {
        String userRole = request.getParameter(Credentials.USER_ROLE);
        if (StringUtils.isEmpty(userRole)) {
            userRole = String.valueOf(UserRoleType.STUDENT.getId()); // FIXME 缺省使用User用户登录
        }

        boolean rememberMe;
        if ("1".equals(request.getParameter(Credentials.REMEMBER_ME))) {
            rememberMe = true;
        } else {
            rememberMe = false;
        }

        return new PassportCredentials(request.getParameter(Credentials.USER_NAME),
            request.getParameter(Credentials.PASSWORD), userRole, request.getParameter(Credentials.COUNTRY_CODE),
            isSms, rememberMe, AccountType.PASSPORT.getCode());
    }

    protected Credentials generateCredentials(HttpServletRequest request, boolean isSms) {
        String appId = request.getParameter(APPID);
        if (StringUtils.isBlank(appId)) {
            logger.debug("generateCredentials : appId is empty");
            appId = String.valueOf(AccountType.USER.getCode()); // FIXME 缺省使用User用户登录，不会走到Passport用户
        }

        logger.info("request params: appId={}, userName={}", appId, request.getParameter(Credentials.USER_NAME));

        AccountType accountType = AccountType.getAccountTypeByCode(Integer.valueOf(appId));
        Credentials credentials = null;
        switch (accountType) {
            case ORG:
                credentials =
                    new JigouCredentials(request.getParameter(Credentials.USER_NAME),
                        request.getParameter(JigouCredentials.COUNTRYCODE), request.getParameter(Credentials.PASSWORD));
                break;
            case ORG_SUB_ACCT:
                credentials =
                    new JigouCascadeAccountCredentials(request.getParameter(Credentials.USER_NAME),
                        request.getParameter(Credentials.PASSWORD));
                break;
            case USER:
                credentials =
                    new UserCredentials(request.getParameter(Credentials.USER_NAME),
                        request.getParameter(Credentials.PASSWORD), isSms);
                break;
            case ORG_TEACHER:
                credentials =
                    new OrgTeacherCredentials(request.getParameter(Credentials.USER_NAME),
                        request.getParameter(Credentials.PASSWORD), isSms);
                break;
            case MOBILE:
                credentials =
                    new MobileCredentials(request.getParameter(Credentials.USER_NAME),
                        request.getParameter(Credentials.PASSWORD));
                break;
            case PASSPORT:
            default:
                credentials = generatePassportCredentials(request, isSms);
                break;
        }

        credentials.setRememberMe("1".equals(request.getParameter(Credentials.REMEMBER_ME)));

        String userRole = request.getParameter(Credentials.USER_ROLE);
        if (StringUtils.isEmpty(userRole)) {
            userRole = String.valueOf(UserRoleType.STUDENT.getId()); // FIXME 缺省使用User用户登录
        }
        if (credentials.getUserRole() == null) {
            credentials.setUserRole(Integer.parseInt(userRole));
        }

        return credentials;
    }

    protected Credentials generateCredentials(HttpServletRequest request) {
        return generateCredentials(request, false);
    }

    protected String getTgtId(HttpServletRequest request, Integer appId) {
        AccountType accountType = AccountType.getAccountTypeByCode(appId);
        switch (accountType) {
            case USER:
            case ORG_TEACHER:
                return cookieRetrievingCookieGenerator.retrieveUserCookieValue(request);
            default:
                return cookieRetrievingCookieGenerator.retrieveCookieValue(request);
        }
    }

    protected LoginInfoDto getLoginInfo(HttpServletRequest request, Integer appId) {
        String ticketGrantingTicketId = getTgtId(request, appId);
        Ticket ticket = ticketRegistry.getTicket(ticketGrantingTicketId);
        if (ticket == null) {
            return null;
        }

        Authentication authentication = ((TicketGrantingTicket) ticket).getAuthentication();
        if (authentication == null) {
            return null;
        }

        LoginInfoDto loginInfoDto = new LoginInfoDto();
        loginInfoDto.setMobile((String) authentication.getAttributes().get(
            AuthenticationMetaDataPopulator.ACCOUNT_MOBILE));

        Object tmpAccountId = null;
        AccountType accountType = AccountType.getAccountTypeByCode(appId);
        switch (accountType) {
            case USER:
            case ORG_TEACHER:
            case ORG:
            case ORG_SUB_ACCT:
                tmpAccountId = authentication.getAttributes().get(AuthenticationMetaDataPopulator.ACCOUNT_ID);
                break;
            case PASSPORT:
            default:
                tmpAccountId = authentication.getAttributes().get(AuthenticationMetaDataPopulator.PASSPORT_ID);
                break;
        }

        if (tmpAccountId != null) {
            loginInfoDto.setAccountId(Long.parseLong(tmpAccountId.toString()));
        }

        return loginInfoDto;
    }

    protected void handleLogout(String ticketGrantingTicketId, HttpServletRequest request, HttpServletResponse response) {
        try {
            if (ticketGrantingTicketId != null) {
                this.centralAuthenticationService.destroyTicketGrantingTicket(ticketGrantingTicketId);
                logger.info("logout destroyTicketGrantingTicket:{}", ticketGrantingTicketId);
            }
        } catch (Exception e) {
            logger.error("logout error", e);
        } finally {
            String appIdStr = request.getParameter(Credentials.APPID);
            AccountType accountType = null;
            if (StringUtils.isNotEmpty(appIdStr)) {
                accountType = AccountType.getAccountTypeByCode(Integer.parseInt(appIdStr));
            } else {
                accountType =
                    LoginAndLogoutUtil.getByUserRoleType(request.getParameter("userRole"),
                        request.getParameter("orgType"));
            }

            switch (accountType) {
                case USER:
                case ORG_TEACHER:
                    this.cookieRetrievingCookieGenerator.removeUserCookie(response);
                    break;
                default:
                    this.cookieRetrievingCookieGenerator.removeCookie(response);
                    break;
            }

            // 删除共享sessionid，使得师资、客服跳转过来的登录能够退出
            dessionCookieCleaner.removeCookie(response);
            logger.info("logout removeCookie:{}", ticketGrantingTicketId);
        }
    }
}
